﻿'  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
'  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
'  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
'  PURPOSE.
'
'  Author:  Mojo


Imports System.Net
Imports System.Net.Sockets

Public Class cls_m_Socket

#Region "Declares"
    Private userName As String = Nothing
    Private pass As String = Nothing
    Private _socketId As String = Nothing
    Private buf As Integer = 32767
    Private bufB(buf) As Byte
    Private port As Integer
    Private host As String
    Private tmpSock As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
    Public Event onConnect(ByVal socID As String)
    Public Event onError(ByVal Description As String, ByVal Number As Integer)
    Public Event onDataArrival(ByVal socId As String, ByVal _user As String, ByVal _pass As String, _
                               ByVal Data As String, ByVal BytesTotal As Integer)
    Private Event onDisconnect()
    Private Event onConnecting()
#End Region

    Public Sub Connect(ByVal sRemoteHostName As String, ByVal iRemotePort As Integer)
        Try
            port = iRemotePort
            host = sRemoteHostName
            tmpSock = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
            tmpSock.BeginConnect(New IPEndPoint(Dns.GetHostEntry(host).AddressList(0), port), AddressOf sockConnected, tmpSock)
            RaiseEvent onConnecting()
        Catch
            RaiseEvent onError(Err.Description, Err.Number)
            Exit Sub
        End Try
    End Sub

    Public Sub SendData(ByVal sData As String)
        Try
            tmpSock.BeginSend(System.Text.Encoding.Default.GetBytes(sData), 0, System.Text.Encoding.Default.GetBytes(sData).Length, 0, AddressOf sockSendEnd, tmpSock)
        Catch
            RaiseEvent onError(Err.Description, Err.Number)
            Exit Sub
        End Try
    End Sub

    Public Sub Close()
        Try
            tmpSock.Shutdown(SocketShutdown.Both)
        Catch
        End Try
        tmpSock.Close()
    End Sub

    Public Property RemoteHost() As String
        Get
            Try
                Return host
            Catch
                RaiseEvent onError(Err.Description, Err.Number)
                RemoteHost = Nothing
                Exit Property
            End Try
        End Get

        Set(ByVal sRemoteHost As String)
            Try
                host = sRemoteHost
            Catch
                RaiseEvent onError(Err.Description, Err.Number)
                Exit Property
            End Try
        End Set
    End Property

    Public Property RemotePort() As Integer
        Get
            Try
                Return port
            Catch
                RaiseEvent onError(Err.Description, Err.Number)
                Exit Property
            End Try
        End Get

        Set(ByVal iRemotePort As Integer)
            Try
                port = iRemotePort
            Catch
                RaiseEvent onError(Err.Description, Err.Number)
                Exit Property
            End Try
        End Set
    End Property

    Public Property sockID() As Integer
        Get
            Try
                Return _socketId
            Catch
                RaiseEvent onError(Err.Description, Err.Number)
                Exit Property
            End Try
        End Get

        Set(ByVal _socID As Integer)
            Try
                _socketId = _socID
            Catch
                RaiseEvent onError(Err.Description, Err.Number)
                Exit Property
            End Try
        End Set
    End Property

    Public Function Connected() As Boolean
        Try
            Return tmpSock.Connected
        Catch
            RaiseEvent onError(Err.Description, Err.Number)

            Exit Function
        End Try
    End Function

    Private Sub sockConnected(ByVal ar As IAsyncResult)
        Try
            If tmpSock.Connected = False Then RaiseEvent onError("Connection refused.", Err.Number) : Exit Sub
            tmpSock.BeginReceive(bufB, 0, buf, 0, AddressOf sockDataArrival, tmpSock)
            RaiseEvent onConnect(_socketId)
        Catch
            RaiseEvent onError(Err.Description, Err.Number)
            Exit Sub
        End Try
    End Sub

    Private Sub sockDataArrival(ByVal ar As IAsyncResult)
        Dim bytesRead As Integer
        Try
            bytesRead = tmpSock.EndReceive(ar)
        Catch
            Exit Sub
        End Try
        Try
            Dim Data() As Byte = bufB
            If bytesRead = 0 Then
                tmpSock.Shutdown(SocketShutdown.Both)
                tmpSock.Close()
                RaiseEvent onDisconnect()
                Exit Sub
            End If
            ReDim bufB(buf)
            tmpSock.BeginReceive(bufB, 0, buf, 0, AddressOf sockDataArrival, tmpSock)
            RaiseEvent onDataArrival(sockID, userName, pass, Mid(System.Text.Encoding.Default.GetChars(Data), 1, bytesRead), bytesRead)
        Catch
            RaiseEvent onError(Err.Description, Err.Number)

            Exit Sub
        End Try
    End Sub

    Private Sub sockSendEnd(ByVal ar As IAsyncResult)
        Try
            Dim tmpSock As Socket = CType(ar.AsyncState, Socket)
            Dim bytesSent As Integer = tmpSock.EndSend(ar)
        Catch
            RaiseEvent onError(Err.Description, Err.Number)
            Exit Sub
        End Try
    End Sub

End Class
